import time

import numpy as np
from utils.serial_communication import SerialCommunication
from utils.fpga_communication import FpgaSerialCommunication
import gradio as gr


class Control:

	def __init__(self, plt_fpga):
		self.can_comm = SerialCommunication()  #位移台
		self.plt_fpga = plt_fpga
		self.fpga_comm = FpgaSerialCommunication()  # fpga
		self.cur_angel = 0
		self.need_angel = 0
		self.init_angel = 0
		self.poly_fit_function = self.poly_fit()

	def is_number(self, s):
		try:
			float(s)
			return True
		except ValueError:
			pass
		try:
			import unicodedata
			unicodedata.numeric(s)
			return True
		except (TypeError, ValueError):
			pass
		return False

	#按钮测试角度方法
	def fun_btn_angle_set(self, angle):
		if self.can_comm.connected:  #检测是否串口连接
			angle = float(angle)
			self.can_comm.will_steer_angel = angle
		else:
			gr.Warning("串口未连接")
			return False

	def fun_btn_angle_get(self):
		if self.can_comm.connected:  #检测是否串口连接
			angle = self.can_comm.cur_pos
			return angle
		else:
			gr.Warning("串口未连接")
			return 0

	#按钮canbus串口连接
	def fun_btn_canbus_connect(self, port_name, baudrate, bytesize, parity, stopbits):
		try:
			baudrate = int(baudrate)
			bytesize = int(bytesize)
			stopbits = int(stopbits)
			if self.can_comm.connect(port_name, baudrate, bytesize, parity, stopbits):
				gr.Info("串口连接")
			else:
				gr.Warning("串口连接失败")
		except:
			gr.Warning("参数设置错误")

	#按钮canbus串口关闭
	def fun_btn_canbus_disconnect(self):
		if self.can_comm.disconnect():
			gr.Info("串口关闭")
		else:
			gr.Warning("串口关闭失败")

	#按钮FPGA串口连接
	def fun_btn_fpga_connect(self, port_name, baudrate, bytesize, parity, stopbits):
		try:
			baudrate = int(baudrate)
			bytesize = int(bytesize)
			stopbits = int(stopbits)
			if self.fpga_comm.connect(port_name, baudrate, bytesize, parity, stopbits):
				gr.Info("串口连接")
			else:
				gr.Warning("串口连接失败")
		except:
			gr.Warning("参数设置错误")

	#按钮FPGA串口串口关闭
	def fun_btn_fpga_disconnect(self):
		if self.fpga_comm.disconnect():
			gr.Info("串口关闭")
		else:
			gr.Warning("串口关闭失败")

	def fun_btn_fpga_test(self):
		self.fpga_comm.run_once()
		print(self.fpga_comm.recieve_data)

	def is_within_range(self, num1, num2):
		if num2:
			return abs(num1 - num2) <= 0.05
		else:
			return False

	#一维拟合
	def poly_fit(self):
		x_data = np.array([0, 27.8, 29.7, 38.9, 39.2, 39.8, 45])
		y_data = np.array([1050, 978, 965, 935, 922, 912, 900])
		degree = 3
		coefficients = np.polyfit(x_data, y_data, degree)
		fitted_function = np.poly1d(coefficients)
		return fitted_function

	def fun_btn_run(self):
		# 1.先检查fpga和电机通信连接是否正常
		if (self.can_comm.connected and self.fpga_comm.connected):
			# 2.初始化所有缓存，对电机位置进行初始化
			#self.can_comm.steer_angel(self.init_angel, 5, 0.8)
			self.can_comm.will_steer_angel = self.init_angel
			self.need_angel = 0
			self.fpga_comm.datalist = []
			self.fpga_comm.recieve_data = ""
			self.can_comm.recieve_data = ""
			self.plt_fpga.del_fpgalist()
			self.cur_angel = 0
			# 3.向电机发出位置信号
			# 4.向电机发出询问当前位置信号，如果在误差以内，则继续，不然再次发送位置信号，后再次询问当前位置判断
			# 5.向fpga发出信号，要求发送检测数据
			once_add_angel = 45 / 500  #一次增加这么多度
			#初始化到self.init_angel度
			self.can_comm.will_steer_angel = self.init_angel
			while True:
				print(self.can_comm.cur_pos)
				if (self.is_within_range(self.init_angel, self.can_comm.cur_pos)):
					break
				time.sleep(0.01)

			for i in range(500):
				self.need_angel = i * once_add_angel + self.init_angel
				self.can_comm.will_steer_angel = self.need_angel
				# while True:
				# 	if (self.is_within_range(self.need_angel, self.can_comm.cur_pos)):
				# 		break
				time.sleep(0.08)
				self.fpga_comm.run_once()
				print(self.can_comm.cur_pos)
				if(self.can_comm.cur_pos>60):
					self.plt_fpga.add_fpga_data(self.fpga_comm.result, 0,
												self.poly_fit_function(0))
				else:
					self.plt_fpga.add_fpga_data(self.fpga_comm.result, self.can_comm.cur_pos,
												self.poly_fit_function(self.can_comm.cur_pos))
			gr.Info("数据收集完成，请点击刷新表格")
		else:
			gr.Warning("未连接")
# 6.收到合法数据，使用add_data放入list里。又开始重复3，4，5。直到45度


if __name__ == "__main__":
	def poly_fit():
		x_data = np.array([0, 27.8, 29.7, 38.9, 39.2, 39.8, 45])
		y_data = np.array([900, 912, 922, 935, 965, 978, 1050])
		degree = 3
		coefficients = np.polyfit(x_data, y_data, degree)
		fitted_function = np.poly1d(coefficients)
		return fitted_function


	a = poly_fit()
	b = a(45)
	print(b)
